在上一篇文章「」中我們介紹了聚合管線的操作,在 MongoDB 官方文件中我們可以看到有許多運算子支持對管線中各個階段的操作,今天這篇文章先來介紹其中兩個:$project 及 $bucket。
我們先來查看 orders 這個 collection 的資料: db.orders.find()
之前有學過可以使用 projection 的概念來回傳指定的欄位:
過濾 status 為 finished 的資料:db.orders.find({status: "finished"})
過濾 status 為 finished 的資料,且只回傳 name 欄位:db.orders.find({status: "finished"}, {name: 1})
過濾 status 為 finished 的資料,且只回傳 name 及 status 欄位:db.orders.find({status: "finished"}, {name: 1, status: 1})
過濾 status 為 finished 的資料,且只回傳 name 及 status 欄位,而不回傳 _id:db.orders.find({status: "finished"}, {name: 1, status: 1, _id: 0})
我們也可以使用 $project 來達成上方指令一樣的結果:
db.orders.aggregate(
[
{$match: {status: "finished"}},
{$project: {name: 1, status: 1, _id: 0}}
]
)
也可以產生新的欄位 "new":
db.orders.aggregate(
[
{
$match: { status: "finished" } },
{
$project:
{
name: 1,
status: 1,
_id: 0,
new: ["$amount", "$name"]
}
}
]
)
我們如果想回傳 name 欄位,並將 value 改成大寫,可以使用 $toUpper:
db.orders.aggregate(
[
{
$match: { status: "finished" } },
{
$project:
{
name: {$toUpper: "$name"}
}
}
]
)
也可以新增一欄位 "new",紀錄某人花了多少錢:
db.orders.aggregate(
[
{
$match: { status: "finished" } },
{
$project:
{
name: {$toUpper: "$name"},
new: {
$concat: ["$name", " spend ", {$toString: "$amount"}]
}
}
}
]
)
新增一欄位 "flag",若 amount > 200 flag 為 big,若 amount ≤ 200 flag 為 small:
db.orders.aggregate(
[
{
$match: { status: "finished" } },
{
$project:
{
name: {$toUpper: "$name"},
new: {
$concat: ["$name", " spend ", {$toString: "$amount"}]
},
flag: {
$cond: {
if: {$gt: ["$amount", 200]},
then: "big",
else: "small"
}
}
}
}
]
)
我們先新增 test 這個 collection:
db.test.insertMany(
[
{
name: "Jack",
hobby: [
"Reading",
"Cooking",
"Running"
]
},
{
name: "Mark",
hobby: [
"Cooking",
"Singing",
]
}
]
)
計算每個人的嗜好有幾個,新增一欄位 "numHobby" 來記錄:
db.test.aggregate(
[
{
$project:{
_id: 0,
name: 1,
numHobby: {
$size: "$hobby"
}
}
}
]
)
我們可以使用 $slice 運算子去取得 array 中的特定元素
db.test.aggregate(
[
{
$project:{
_id: 0,
name: 1,
numHobby: {
$size: "$hobby"
},
hobby: {
$slice: ["$hobby", 0, 1]
}
}
}
]
)
db.test.aggregate(
[
{
$project:{
_id: 0,
name: 1,
numHobby: {
$size: "$hobby"
},
hobby: {
$slice: ["$hobby", 0, 3]
}
}
}
]
)
對於更多聚合管線操作運算子的使用方法,可以參考以下的官方文件說明:
我們可以使用 $bucket 運算子對資料進行分類。
先來查看 movie 這個 collection:db.movie.findOne()
使用 $bucket 進行資料分類,每個分類為一個 bucket
db.movie.aggregate(
[
{
$bucket:{
groupBy: "$year",
boundaries: [1990, 1995, 2000, 2005, 2010, 2015, 2020],
output: {
numMovies: {$sum: 1},
avgScore: {$avg: "$imdb_score"}
}
}
}
]
)
今天介紹了兩種操作聚合管線的運算子 $project 及 $bucket,下一篇會接著介紹其他聚合管線的運算子。